# -*- coding: utf-8 -*-
# @Author: bao
# @Date:   2017-01-23 22:34:13
# @Last Modified by:   bao
# @Last Modified time: 2017-02-17 17:19:45

import sys
sys.path.append("..")

from Topology.Jellyfish import *
from CoreSim.Routing import *

class K_Shortest_Path(Routing):
	"""
	This routing approach is specific for jellyfish topology
	"""
	def __init__(self, topo):
		Routing.__init__(self, topo)
		self.k = topo.k # k shortest path threshold
		self.numOfHosts = topo.numOfHosts

	def BuildAllPath(self):
		self.CalculateAllPath()

	def BuildPath(self, srcId, dstId):
		self.CalculatePath(srcId, dstId)

	def CalculateAllPath(self):
		"""
		This function calculate path between each pair of servers with k shortest path routing
		There exsit multi-paths between the src and dst
		Using random selection
		"""
		for srcHostId in range(1, self.numOfHosts + 1):
			for dstHostId in range(1, self.numOfHosts + 1):
				self.CalculatePath(srcId=srcHostId, dstId=dstHostId)

	def CalculatePath(self, srcId, dstId):
		# only self id is contained, if destination is self
		if (srcId, dstId) not in self.pathList:
			self.pathList[srcId, dstId] = []
			if srcId == dstId:
				self.pathList[srcId, dstId].append([srcId])
				return
			srcToRId = self.GetToRId(srcId)
			dstToRId = self.GetToRId(dstId)
			srcToRNodeId = self.topo.ConvertToNodeId(srcToRId, TOR)
			dstToRNodeId = self.topo.ConvertToNodeId(dstToRId, TOR)
			# if src and dst are in the same parent tor switch
			if srcToRId == dstToRId:
				self.pathList[srcId, dstId].append([srcId, srcToRNodeId, dstId])
				return
			else:
				k_pathes = []
				tmp_cutoff = 1
				while len(k_pathes) <= self.k and tmp_cutoff < 10:
					k_pathes = list(nx.all_simple_paths(self.topo.com_network, source=srcToRId, target=dstToRId, cutoff=tmp_cutoff))
					tmp_cutoff += 1
				#print k_pathes
				for path in k_pathes:
					pathList = [srcId]
					for ToRId in path:
						ToRNodeId = self.topo.ConvertToNodeId(ToRId, TOR)
						pathList.append(ToRNodeId)
					pathList.append(dstId)
					self.pathList[srcId, dstId].append(pathList)
				#print 'self.pathList', self.pathList[srcId, dstId]

	def GetToRId(self, hostId):
		return (hostId-1)/self.topo.numOfHost + 1